package com.xiaoshuidi.cloud.module.iot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.module.iot.api.device.vo.AmmeterInfoResModel;
import com.xiaoshuidi.cloud.module.iot.api.device.vo.DeviceDosageVo;
import com.xiaoshuidi.cloud.module.iot.common.ResultModel;
import com.xiaoshuidi.cloud.module.iot.controller.admin.doorlock.vo.OperateThirdDeviceRequestModel;
import com.xiaoshuidi.cloud.module.iot.controller.admin.doorlock.vo.OperateThirdDeviceResponseModel;
import com.xiaoshuidi.cloud.module.iot.dal.model.AccessTokenRequestWrapperModel;
import com.xiaoshuidi.cloud.module.iot.dal.model.AccessTokenResponseWrapperModel;
import com.xiaoshuidi.cloud.module.iot.dal.model.ammeter.*;
import com.xiaoshuidi.cloud.module.iot.dal.model.callback.SendMessageVo;
import com.xiaoshuidi.cloud.module.iot.dal.model.watermeter.details.WaterMeterReportRequestModel;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.DevicePrice;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbAccountDo;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbDeviceDo;
import com.xiaoshuidi.cloud.module.iot.dal.pojo.TbDeviceDosageDo;
import com.xiaoshuidi.cloud.module.iot.dal.repository.DeviceDosageRepository;
import com.xiaoshuidi.cloud.module.iot.dal.repository.DevicePriceRepository;
import com.xiaoshuidi.cloud.module.iot.dal.repository.DeviceRepository;
import com.xiaoshuidi.cloud.module.iot.dal.repository.TbAccountRepository;
import com.xiaoshuidi.cloud.module.iot.dal.util.SendMqMessageUtil;
import com.xiaoshuidi.cloud.module.iot.enums.BrandEnum;
import com.xiaoshuidi.cloud.module.iot.enums.PeakValleyEnum;
import com.xiaoshuidi.cloud.module.iot.enums.WaterElectricityReportType;
import com.xiaoshuidi.cloud.module.iot.service.*;
import com.xiaoshuidi.cloud.module.rooms.api.sdiot.IotRoomDeviceApi;
import com.xiaoshuidi.cloud.module.rooms.vo.PriceInfo;
import com.xiaoshuidi.cloud.module.rooms.vo.RoomContractVO;
import com.xiaoshuidi.cloud.module.rooms.vo.RoomDevicePeakValleyPriceVo;
import com.xiaoshuidi.cloud.module.rooms.vo.RoomSdiotDeviceMappingVo;
import net.sf.cglib.beans.BeanCopier;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.*;
import java.util.*;

/**
 * @author Sky
 * create 2019/07/01
 * email sky.li@ixiaoshuidi.com
 **/
@Service
public class AmmeterServiceImpl implements AmmeterService {

    private final static Logger LOGGER = LoggerFactory.getLogger(AmmeterServiceImpl.class);

    @Autowired
    private TbAccountRepository tbAccountDataAccess;

    @Autowired
    private LocalAccessTokenServcie localAccessTokenServcie;

    @Autowired
    private DeviceDosageRepository deviceDosageDataAccess;
    @Autowired
    private DeviceRepository ammeterDataAccess;
    @Autowired
    private DevicePriceRepository devicePriceAccess;

    @Autowired
    private IotRoomDeviceApi roomDeviceApi;
    @Autowired
    private DeviceRepository waterMeterDataAccess;
    @Autowired
    private DeviceRepository deviceDataAccess;
    @Resource
    private StreamBridge streamBridge;
    @Autowired
    IotRoomDeviceApi iotRoomDeviceApi;
    @Autowired
    private WaterElectricityReportService waterElectricityReportService;

    /**
     * 第三方公共业务-刷新电表
     *
     * @param ammeterInfoReqModel
     * @return
     */
    public ResultModel<AmmeterInfoResModel> refreshAmmeterInfo1(AmmeterInfoReqModel ammeterInfoReqModel) throws Exception {
        ResultModel<AmmeterInfoResModel> resultModel = null;
        ResultModel<AccessTokenResponseWrapperModel> accessTokenResultModel = this.getAccessToken(ammeterInfoReqModel.getTbDeviceDo().getApiNo());
        if (ResultModel.CODE_SUCCESS.equals(accessTokenResultModel.getCode())) {
            ThirdInstanceService thirdInstanceService = ThirdInstanceFactory.produce(ammeterInfoReqModel.getTbDeviceDo().getBrandNo());
            OperateThirdDeviceRequestModel operateThirdDeviceRequestModel = new OperateThirdDeviceRequestModel();
            operateThirdDeviceRequestModel.setAccessToken(accessTokenResultModel.getData().getAccessToken());
            operateThirdDeviceRequestModel.setLoginName(accessTokenResultModel.getData().getAppId());
            operateThirdDeviceRequestModel.setLoginKey(accessTokenResultModel.getData().getAppKey());
            AmmeterInfoResModel ammeterInfoResModel = thirdInstanceService.refreshAmmeterInfo(ammeterInfoReqModel.getTbDeviceDo(), operateThirdDeviceRequestModel);
            resultModel = ResultModel.createSuccess(ammeterInfoResModel);
        } else {
            resultModel = ResultModel.createFail(accessTokenResultModel.getCode(), accessTokenResultModel.getMsg());
        }
        return resultModel;
    }


    @Override
    public ResultModel<AmmeterInfoResModel> refreshAmmeterInfo(AmmeterInfoReqModel ammeterInfoReqModel) throws Exception {
        AmmeterInfoResModel ammeterInfoResModel = new AmmeterInfoResModel();
        TbDeviceDo tbDeviceDo = ammeterDataAccess.getAmmeterInfoByDeviceNo(ammeterInfoReqModel.getDeviceNo());
        BeanCopier.create(TbDeviceDo.class, AmmeterInfoResModel.class, false).copy(tbDeviceDo, ammeterInfoResModel, null);
        //调用第三方刷新电表服务
        ammeterInfoReqModel.setTbDeviceDo(tbDeviceDo);
        ResultModel<AmmeterInfoResModel> resultModel = this.refreshAmmeterInfo1(ammeterInfoReqModel);
        LOGGER.info("调用biz第三方公共刷新电表服务,设备编号：{},返回结果:{}", tbDeviceDo.getDeviceNo(), JSONObject.toJSONString(resultModel));
        if (ResultModel.CODE_SUCCESS.equals(resultModel.getCode())) {
            AmmeterInfoResModel data = resultModel.getData();
            BeanUtil.copyProperties(data, ammeterInfoResModel, new CopyOptions().setIgnoreNullValue(true));
            //蚂蚁iot集成品牌或者Bite设备或者阿里智慧人居设备或者超仪设备
            if (BrandEnum.BITE.getBrand().equals(tbDeviceDo.getBrandNo()) || tbDeviceDo.getBrandNo().startsWith("ant")
                    || BrandEnum.ALI_HOMELINK.getBrand().equals(tbDeviceDo.getBrandNo()) || BrandEnum.CHAOYI.getBrand().equals(tbDeviceDo.getBrandNo())
                    || BrandEnum.WEILIU.getBrand().equals(tbDeviceDo.getBrandNo()) || BrandEnum.MIJIAYUAN.getBrand().equals(tbDeviceDo.getBrandNo())
                    || BrandEnum.DANBEI.getBrand().equals(tbDeviceDo.getBrandNo()) || BrandEnum.WOTA.getBrand().equals(tbDeviceDo.getBrandNo())
                    || BrandEnum.ZHENGTAI.getBrand().equals(tbDeviceDo.getBrandNo()) || BrandEnum.YINTONGWULIAN.getBrand().equals(tbDeviceDo.getBrandNo())
                    ||BrandEnum.YUNDING.getBrand().equals(tbDeviceDo.getBrandNo())
                    || BrandEnum.AIKE.getBrand().equals(tbDeviceDo.getBrandNo())) {
                //如果没有获取读数，代表刷新失败
                if (data.getCurrentReading() == null) {
                    return ResultModel.createNativeFail("刷新失败,请联系厂商!");
                }
                if (null != ammeterInfoReqModel.getRoomId()) {
                    ammeterInfoResModel.setRoomId(ammeterInfoReqModel.getRoomId());
                }
                //新增读数记录,并更新数据，预付费断电逻辑
                this.disposeDeviceDosage(tbDeviceDo, ammeterInfoResModel, ammeterInfoReqModel.isCharging());
            }
        } else {
            return ResultModel.createNativeFail("刷新失败,请联系厂商!");
        }
        return ResultModel.createSuccess(ammeterInfoResModel);
    }


    /**
     * 处理刷新最新数据
     *
     * @param currentDevice
     * @param ammeterInfoResModel
     * @param charging            是否扣费
     */
    private void disposeDeviceDosage(TbDeviceDo currentDevice, AmmeterInfoResModel ammeterInfoResModel, boolean charging) {

        // 有峰谷电读数的，按峰谷电读数执行计算和存储，无峰谷电按原方案处理
        List<AmmeterInfoResModel.PeakValley> peakValleyList = ammeterInfoResModel.getPeakValleyList();
        if (CollectionUtils.isNotEmpty(peakValleyList)
                || BrandEnum.LEIYOU.getBrand().equals(currentDevice.getBrandNo())
                || BrandEnum.LUOSAI.getBrand().equals(currentDevice.getBrandNo())) {
            this.disposePeakValleyDeviceDosage(currentDevice, ammeterInfoResModel, charging);
            return;
        }

        //增加水电表抄表记录，并更新水电表读数
        TbDeviceDosageDo tbDeviceDosageDo = new TbDeviceDosageDo();
        LocalDate today = LocalDate.now();
        tbDeviceDosageDo.setDosageDate(today);
        tbDeviceDosageDo.setEndAmount(ammeterInfoResModel.getCurrentReading());
        if (tbDeviceDosageDo.getEndAmount().compareTo(currentDevice.getCurrentReading()) < 0) {
            return;
        }
        //云丁电表处理分摊电量
        Double shareCurrentReading=ammeterInfoResModel.getShareCurrentReading();
        if(null!=shareCurrentReading) {
            if (shareCurrentReading.compareTo(currentDevice.getShareCurrentReading()) < 0) {
                return;
            }
        }else{
            shareCurrentReading=0.0;
        }

        currentDevice = ammeterDataAccess.getAmmeterInfoByDeviceNo(currentDevice.getDeviceNo());

        //第一次读数上传
        if (currentDevice.getCurrentReading().compareTo(0.0) == 0) {
            tbDeviceDosageDo.setStartAmount(tbDeviceDosageDo.getEndAmount());
        } else {
            tbDeviceDosageDo.setStartAmount(currentDevice.getCurrentReading());
        }
        //分摊电量
        BigDecimal apportionAmount = BigDecimal.valueOf(shareCurrentReading).subtract(BigDecimal.valueOf(currentDevice.getShareCurrentReading()));
        BigDecimal totalAmount = BigDecimal.valueOf(tbDeviceDosageDo.getEndAmount()).subtract(BigDecimal.valueOf(tbDeviceDosageDo.getStartAmount()));
        tbDeviceDosageDo.setTotalAmount(totalAmount.doubleValue());
        tbDeviceDosageDo.setDeviceNo(currentDevice.getDeviceNo());
        //获取阶梯水电价格 1.获取本年度的总度数 2.根据阶梯配置判断使用哪种价格
        Double readAllAccount = 0.0;
        Calendar now = Calendar.getInstance();
        int year = now.get(Calendar.YEAR);
        DevicePrice devicePrice = devicePriceAccess.getDevicePriceVo(Long.valueOf(year), currentDevice.getDeviceNo());
        //记录总度数
        if (null == devicePrice) {
            DevicePrice devicePriceVo = new DevicePrice();
            devicePriceVo.setYear(Long.valueOf(year));
            devicePriceVo.setDeviceThireNo(currentDevice.getDeviceThirdNo());
            devicePriceVo.setDeviceNo(currentDevice.getDeviceNo());
            devicePriceVo.setReadAccount(tbDeviceDosageDo.getEndAmount());
            devicePriceAccess.save(devicePriceVo);
        } else {
            //更新总度数
            readAllAccount = totalAmount.add(BigDecimal.valueOf(devicePrice.getReadAccount())).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
            devicePrice.setReadAccount(readAllAccount);
            devicePriceAccess.updateById(devicePrice);
        }
        LOGGER.info("上次读数：" + JSONObject.toJSONString(currentDevice.getCurrentReading()));
        //获取本次消费金额
        CommonResult<List<PriceInfo>> infoList = roomDeviceApi.getDevicePrice(currentDevice.getDeviceNo(), currentDevice.getDeviceType());
        LOGGER.info("获取阶梯水电数据：{},deviceNo：{}" + JSONObject.toJSONString(infoList), currentDevice.getDeviceNo());
        BigDecimal accountAmount = SendMqMessageUtil.compute(BigDecimal.valueOf(readAllAccount).subtract(totalAmount), BigDecimal.valueOf(readAllAccount), infoList.getData());
        LOGGER.info("获取本次消费金额：" + JSONObject.toJSONString(accountAmount));
        BigDecimal shareAmount = SendMqMessageUtil.compute(BigDecimal.valueOf(readAllAccount).subtract(apportionAmount), BigDecimal.valueOf(readAllAccount), infoList.getData());
        LOGGER.info("获取分摊消费金额：" + JSONObject.toJSONString(shareAmount));
        if (charging)
            tbDeviceDosageDo.setAmount(accountAmount.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
        else {
            tbDeviceDosageDo.setAmount(0d);
        }
        String mesgId = UUID.randomUUID().toString();
        tbDeviceDosageDo.setMesgId(mesgId);
        tbDeviceDosageDo.setShareAmount(shareAmount.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        tbDeviceDosageDo.setShareRading(apportionAmount.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
        currentDevice.setCurrentReading(ammeterInfoResModel.getCurrentReading());
        currentDevice.setPowerStatus(ammeterInfoResModel.getPowerStatus());
        currentDevice.setOnlineStatus(ammeterInfoResModel.getOnlineStatus());
        LocalDateTime ldt = LocalDateTime.ofInstant(ammeterInfoResModel.getReportTime().toInstant(), ZoneOffset.UTC);
        currentDevice.setReportTime(ldt);
        currentDevice.setUpdateTime(LocalDateTime.now());
        //修改tb_device
//        int updateTbDeviceRecord = ammeterDataAccess.updateTbDeviceRecord(currentDevice);
        boolean updateTbDeviceRecord = ammeterDataAccess.updateTbDeviceRecordAndVersion(currentDevice);
        if (updateTbDeviceRecord) {
            //新增读数上报记录
            boolean addDosageResult = deviceDosageDataAccess.save(tbDeviceDosageDo);
            ResultModel<RoomSdiotDeviceMappingVo> resultModel = iotRoomDeviceApi.getRoomInfoByDeviceNo(currentDevice.getDeviceNo(), currentDevice.getDeviceType());
            LOGGER.info("根据deviceNo获取房间信息：" + JSONObject.toJSONString(resultModel));
            Long roomId = resultModel.getData().getRoomHouseId();
            if (totalAmount.compareTo(BigDecimal.ZERO) > 0) {
                //产生报表数据
                waterElectricityReportService.save(roomId, currentDevice.getDeviceNo(), currentDevice.getDeviceThirdNo(), tbDeviceDosageDo, WaterElectricityReportType.ELECTRICITY.getCode(), currentDevice.getTenantId());
            }
            //发送消息到钱包更新余额
            if (CollectionUtil.isNotEmpty(infoList.getData()) && totalAmount.compareTo(BigDecimal.ZERO) > 0 && charging) {

                SendMessageVo messageVo = new SendMessageVo();
                messageVo.setAmount(accountAmount.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
                messageVo.setShareAmount(shareAmount.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
                messageVo.setDevice(currentDevice.getDeviceNo());
                messageVo.setMsgId(mesgId);
                messageVo.setRoomId(String.valueOf(roomId));
                messageVo.setTradeTime(new Date());
                messageVo.setCharging("电费");
                LOGGER.info("发送钱包数据：" + JSONObject.toJSONString(messageVo));
                boolean send = streamBridge.send("financeAccountBalance-out-0", MessageBuilder.withPayload(messageVo).setHeader("TAGS", "DEDUCT").build());
                LOGGER.info("发送钱包返回：" + JSONObject.toJSONString(send));
            }
//            //处理预付费断电逻辑
//            ResultModel<AmmeterSwitchOnOffResVO> resultModel = this.disposePrepaymentLogic(currentDevice);
//            if (ammeterInfoResModel.getPowerStatus() == 1) {
//                ammeterInfoResModel.setPowerStatus(ResultModel.CODE_SUCCESS.equals(resultModel.getCode()) ? 0 : 1);
//            }
        } else {
            LOGGER.error("刷新电表失败,版本version冲突,设备编号:{},设备名称:{}", currentDevice.getDeviceNo(), currentDevice.getDeviceName());
        }
    }

    /**
     * 处理刷新峰谷电最新数据(含常规电表)
     *
     * @param currentDevice
     * @param ammeterInfoResModel
     * @param charging            是否扣费
     */
    private void disposePeakValleyDeviceDosage(TbDeviceDo currentDevice, AmmeterInfoResModel ammeterInfoResModel, boolean charging) {

        currentDevice = ammeterDataAccess.getAmmeterInfoByDeviceNo(currentDevice.getDeviceNo());

        AmmeterInfoResModel.PeakValley normal = ammeterInfoResModel.getPeakValleyList().stream()
                .filter(bean -> PeakValleyEnum.NORMAL.equals(bean.getType())).findFirst().orElse(null);
        AmmeterInfoResModel.PeakValley spike = ammeterInfoResModel.getPeakValleyList().stream()
                .filter(bean -> PeakValleyEnum.SPIKE.equals(bean.getType())).findFirst().orElse(null);
        AmmeterInfoResModel.PeakValley peak = ammeterInfoResModel.getPeakValleyList().stream()
                .filter(bean -> PeakValleyEnum.PEAK.equals(bean.getType())).findFirst().orElse(null);
        AmmeterInfoResModel.PeakValley plain = ammeterInfoResModel.getPeakValleyList().stream()
                .filter(bean -> PeakValleyEnum.PLAIN.equals(bean.getType())).findFirst().orElse(null);
        AmmeterInfoResModel.PeakValley valley = ammeterInfoResModel.getPeakValleyList().stream()
                .filter(bean -> PeakValleyEnum.VALLEY.equals(bean.getType())).findFirst().orElse(null);

        //增加水电表抄表记录，并更新水电表读数
        TbDeviceDosageDo tbDeviceDosageDo = new TbDeviceDosageDo();
        tbDeviceDosageDo.setDeviceNo(currentDevice.getDeviceNo());
        LocalDate today = LocalDate.now();
        tbDeviceDosageDo.setDosageDate(today);

        tbDeviceDosageDo.setStartAmount(0.0);
        tbDeviceDosageDo.setEndAmount(0.0);
        tbDeviceDosageDo.setTotalAmount(0.0);
        tbDeviceDosageDo.setAmount(0.0);
        // 目前这里没有公摊
        tbDeviceDosageDo.setShareAmount(0.0);
        tbDeviceDosageDo.setShareRading(0.0);

        LOGGER.info("deviceNo：{}, 上次读数：常规->{}, 尖->{}, 峰->{}, 平:{}, 谷:{}",
                currentDevice.getDeviceNo(), currentDevice.getCurrentReading(), currentDevice.getSpikeCurrentReading(),
                currentDevice.getPeakCurrentReading(), currentDevice.getPlainCurrentReading(), currentDevice.getValleyCurrentReading());

        LOGGER.info("deviceNo：{}, 本次读数：常规->{}, 尖->{}, 峰->{}, 平:{}, 谷:{}",
                currentDevice.getDeviceNo(), normal == null ? null : normal.getCurrentReading(), spike == null ? null : spike.getCurrentReading(),
                peak == null ? null : peak.getCurrentReading(), plain == null ? null : plain.getCurrentReading(), valley == null ? null : valley.getCurrentReading());

        BigDecimal usedNormal = BigDecimal.ZERO;
        BigDecimal usedSpike = BigDecimal.ZERO;
        BigDecimal usedPeak = BigDecimal.ZERO;
        BigDecimal usedPlain = BigDecimal.ZERO;
        BigDecimal usedValley = BigDecimal.ZERO;
        if (normal != null) {
            if (normal.getCurrentReading().compareTo(currentDevice.getCurrentReading()) < 0) {
                LOGGER.warn("本次常规读数小于上次读数，做跳过处理！");
                return;
            }
            tbDeviceDosageDo.setEndAmount(normal.getCurrentReading());
            //第一次读数上传
            tbDeviceDosageDo.setStartAmount(currentDevice.getCurrentReading().compareTo(0.0) == 0 ? tbDeviceDosageDo.getEndAmount() : currentDevice.getCurrentReading());
            usedNormal = BigDecimal.valueOf(tbDeviceDosageDo.getEndAmount()).subtract(BigDecimal.valueOf(tbDeviceDosageDo.getStartAmount()));
            tbDeviceDosageDo.setTotalAmount(usedNormal.doubleValue());
        }
        if (spike != null) {
            if (spike.getCurrentReading().compareTo(currentDevice.getSpikeCurrentReading()) < 0) {
                LOGGER.warn("本次尖读数小于上次读数，做跳过处理！");
                return;
            }
            tbDeviceDosageDo.setSpikeEndReading(spike.getCurrentReading());
            //第一次读数上传
            tbDeviceDosageDo.setSpikeStartReading(currentDevice.getSpikeCurrentReading().compareTo(0.0) == 0 ? tbDeviceDosageDo.getSpikeEndReading() : currentDevice.getSpikeCurrentReading());
            usedSpike = BigDecimal.valueOf(tbDeviceDosageDo.getSpikeEndReading()).subtract(BigDecimal.valueOf(tbDeviceDosageDo.getSpikeStartReading()));
        }
        if (peak != null) {
            if (peak.getCurrentReading().compareTo(currentDevice.getPeakCurrentReading()) < 0) {
                LOGGER.warn("本次峰读数小于上次读数，做跳过处理！");
                return;
            }
            tbDeviceDosageDo.setPeakEndReading(peak.getCurrentReading());
            //第一次读数上传
            tbDeviceDosageDo.setPeakStartReading(currentDevice.getPeakCurrentReading().compareTo(0.0) == 0 ? tbDeviceDosageDo.getPeakEndReading() : currentDevice.getPeakCurrentReading());
            usedPeak = BigDecimal.valueOf(tbDeviceDosageDo.getPeakEndReading()).subtract(BigDecimal.valueOf(tbDeviceDosageDo.getPeakStartReading()));
        }
        if (plain != null) {
            if (plain.getCurrentReading().compareTo(currentDevice.getPlainCurrentReading()) < 0) {
                LOGGER.warn("本次平读数小于上次读数，做跳过处理！");
                return;
            }
            tbDeviceDosageDo.setPlainEndReading(plain.getCurrentReading());
            //第一次读数上传
            tbDeviceDosageDo.setPlainStartReading(currentDevice.getPlainCurrentReading().compareTo(0.0) == 0 ? tbDeviceDosageDo.getPlainEndReading() : currentDevice.getPlainCurrentReading());
            usedPlain = BigDecimal.valueOf(tbDeviceDosageDo.getPlainEndReading()).subtract(BigDecimal.valueOf(tbDeviceDosageDo.getPlainStartReading()));
        }
        if (valley != null) {
            if (valley.getCurrentReading().compareTo(currentDevice.getValleyCurrentReading()) < 0) {
                LOGGER.warn("本次谷读数小于上次读数，做跳过处理！");
                return;
            }
            tbDeviceDosageDo.setValleyEndReading(valley.getCurrentReading());
            //第一次读数上传
            tbDeviceDosageDo.setValleyStartReading(currentDevice.getValleyCurrentReading().compareTo(0.0) == 0 ? tbDeviceDosageDo.getValleyEndReading() : currentDevice.getValleyCurrentReading());
            usedValley = BigDecimal.valueOf(tbDeviceDosageDo.getValleyEndReading()).subtract(BigDecimal.valueOf(tbDeviceDosageDo.getValleyStartReading()));
        }

        Long year = Long.valueOf(LocalDate.now().getYear());
        DevicePrice devicePrice = devicePriceAccess.getDevicePriceVo(year, currentDevice.getDeviceNo());
        //记录总度数
        if (null == devicePrice) {
            devicePrice = new DevicePrice();
            devicePrice.setYear(Long.valueOf(year));
            devicePrice.setDeviceThireNo(currentDevice.getDeviceThirdNo());
            devicePrice.setDeviceNo(currentDevice.getDeviceNo());
            devicePrice.setReadAccount(usedNormal.doubleValue());
            devicePrice.setSpikeReadAccount(usedSpike.doubleValue());
            devicePrice.setPeakReadAccount(usedPeak.doubleValue());
            devicePrice.setPlainReadAccount(usedPlain.doubleValue());
            devicePrice.setValleyReadAccount(usedValley.doubleValue());
            devicePriceAccess.save(devicePrice);
        } else {
            //更新总度数
            devicePrice.setReadAccount(devicePrice.getReadAccount() + usedNormal.doubleValue());
            devicePrice.setSpikeReadAccount(devicePrice.getSpikeReadAccount() + usedSpike.doubleValue());
            devicePrice.setPeakReadAccount(devicePrice.getPeakReadAccount() + usedPeak.doubleValue());
            devicePrice.setPlainReadAccount(devicePrice.getPlainReadAccount() + usedPlain.doubleValue());
            devicePrice.setValleyReadAccount(devicePrice.getValleyReadAccount() + usedValley.doubleValue());
            devicePriceAccess.updateById(devicePrice);
        }

        BigDecimal normalUnit = BigDecimal.ZERO;
        BigDecimal spikeUnit = BigDecimal.ZERO;
        BigDecimal peakUnit  = BigDecimal.ZERO;
        BigDecimal plainUnit = BigDecimal.ZERO;
        BigDecimal valleyUnit = BigDecimal.ZERO;
        // TODO 获取峰谷单价
        // 如果是罗赛或者雷优 用新的接口查询单价
        CommonResult<List<RoomDevicePeakValleyPriceVo>> result = roomDeviceApi.getDevicePeakValleyPrice(currentDevice.getDeviceNo(), currentDevice.getDeviceType());
        LOGGER.info("获取峰谷水电单价数据：" + JSONObject.toJSONString(result));
        if (result.isSuccess()) {
            List<RoomDevicePeakValleyPriceVo> data = result.getData();
            if (CollectionUtils.isNotEmpty(data)) {
                RoomDevicePeakValleyPriceVo roomDevicePeakValleyPriceVo = data.get(0);
                if (RoomDevicePeakValleyPriceVo.AMMTER_TYPE_NORMAL.equals(roomDevicePeakValleyPriceVo.getAmmterType())) {
                    // 如果是常规用电，峰谷单价都不计算
                    normalUnit = roomDevicePeakValleyPriceVo.getAmmterPrice() == null ? BigDecimal.ZERO : new BigDecimal(roomDevicePeakValleyPriceVo.getAmmterPrice().toString());
                }
                if (RoomDevicePeakValleyPriceVo.AMMTER_TYPE_PEAK_VALLEY.equals(roomDevicePeakValleyPriceVo.getAmmterType())) {
                    // 如果是峰谷用电，常规单价不计算
                    spikeUnit = roomDevicePeakValleyPriceVo.getAmmterSpikePrice() == null ? BigDecimal.ZERO : new BigDecimal(roomDevicePeakValleyPriceVo.getAmmterSpikePrice().toString());
                    peakUnit = roomDevicePeakValleyPriceVo.getAmmterPeakPrice() == null ? BigDecimal.ZERO : new BigDecimal(roomDevicePeakValleyPriceVo.getAmmterPeakPrice().toString());
                    plainUnit = roomDevicePeakValleyPriceVo.getAmmterPlainPrice() == null ? BigDecimal.ZERO : new BigDecimal(roomDevicePeakValleyPriceVo.getAmmterPlainPrice().toString());
                    valleyUnit = roomDevicePeakValleyPriceVo.getAmmterValleyPrice() == null ? BigDecimal.ZERO : new BigDecimal(roomDevicePeakValleyPriceVo.getAmmterValleyPrice().toString());
                }
            }
        }
        LOGGER.info("获取deviceNo:{},单价：常规->{}, 尖->{}, 峰->{}, 平:{}, 谷:{}", currentDevice.getDeviceNo(), normalUnit, spikeUnit, peakUnit, plainUnit, valleyUnit);
        BigDecimal usedNormalAmount = usedNormal.multiply(normalUnit).setScale(3, BigDecimal.ROUND_HALF_UP);
        BigDecimal usedSpikeAmount = usedSpike.multiply(spikeUnit).setScale(3, BigDecimal.ROUND_HALF_UP);
        BigDecimal usedPeakAmount = usedPeak.multiply(peakUnit).setScale(3, BigDecimal.ROUND_HALF_UP);
        BigDecimal usedPlainAmount = usedPlain.multiply(plainUnit).setScale(3, BigDecimal.ROUND_HALF_UP);
        BigDecimal usedValleyAmount = usedValley.multiply(valleyUnit).setScale(3, BigDecimal.ROUND_HALF_UP);
        LOGGER.info("获取deviceNo:{},计算金额：常规->{}, 尖->{}, 峰->{}, 平:{}, 谷:{}", currentDevice.getDeviceNo(), usedNormalAmount, usedSpikeAmount, usedPeakAmount, usedPlainAmount, usedValleyAmount);
        tbDeviceDosageDo.setAmount(usedNormalAmount.doubleValue());
        tbDeviceDosageDo.setSpikeAmount(usedSpikeAmount.doubleValue());
        tbDeviceDosageDo.setPeakAmount(usedPeakAmount.doubleValue());
        tbDeviceDosageDo.setPlainAmount(usedPlainAmount.doubleValue());
        tbDeviceDosageDo.setValleyAmount(usedValleyAmount.doubleValue());
        String mesgId = UUID.randomUUID().toString();
        tbDeviceDosageDo.setMesgId(mesgId);
        currentDevice.setShareCurrentReading(0.0);
        currentDevice.setPowerStatus(ammeterInfoResModel.getPowerStatus());
        currentDevice.setOnlineStatus(ammeterInfoResModel.getOnlineStatus());
        currentDevice.setCurrentReading(normal == null ? currentDevice.getCurrentReading() : normal.getCurrentReading());
        currentDevice.setReportTime(normal == null ? currentDevice.getReportTime() : LocalDateTime.ofInstant(normal.getReportTime().toInstant(), ZoneOffset.UTC));
        currentDevice.setSpikeCurrentReading(spike == null ? currentDevice.getSpikeCurrentReading() : spike.getCurrentReading());
        currentDevice.setSpikeReportTime(spike == null ? currentDevice.getSpikeReportTime() : LocalDateTime.ofInstant(spike.getReportTime().toInstant(), ZoneOffset.UTC));
        currentDevice.setPeakCurrentReading(peak == null ? currentDevice.getPeakCurrentReading() : peak.getCurrentReading());
        currentDevice.setPeakReportTime(peak == null ? currentDevice.getPeakReportTime() : LocalDateTime.ofInstant(peak.getReportTime().toInstant(), ZoneOffset.UTC));
        currentDevice.setPlainCurrentReading(plain == null ? currentDevice.getPlainCurrentReading() : plain.getCurrentReading());
        currentDevice.setPlainReportTime(plain == null ? currentDevice.getPlainReportTime() : LocalDateTime.ofInstant(plain.getReportTime().toInstant(), ZoneOffset.UTC));
        currentDevice.setValleyCurrentReading(valley == null ? currentDevice.getValleyCurrentReading() : valley.getCurrentReading());
        currentDevice.setValleyReportTime(valley == null ? currentDevice.getValleyReportTime() : LocalDateTime.ofInstant(valley.getReportTime().toInstant(), ZoneOffset.UTC));
        currentDevice.setUpdateTime(LocalDateTime.now());
        //修改tb_device
        boolean updateTbDeviceRecord = ammeterDataAccess.updateTbDeviceRecordAndVersion(currentDevice);
        if (updateTbDeviceRecord) {
            //新增读数上报记录
            boolean addDosageResult = deviceDosageDataAccess.save(tbDeviceDosageDo);
            ResultModel<RoomSdiotDeviceMappingVo> resultModel = iotRoomDeviceApi.getRoomInfoByDeviceNo(currentDevice.getDeviceNo(), currentDevice.getDeviceType());
            LOGGER.info("根据deviceNo获取房间信息：" + JSONObject.toJSONString(resultModel));
            Long roomId = resultModel.getData().getRoomHouseId();

            if (usedNormal.compareTo(BigDecimal.ZERO) > 0) {
                // 产生报表数据
                waterElectricityReportService.save(roomId, currentDevice.getDeviceNo(), currentDevice.getDeviceThirdNo(), tbDeviceDosageDo, WaterElectricityReportType.ELECTRICITY.getCode(), currentDevice.getTenantId());
            }
            if (usedSpike.compareTo(BigDecimal.ZERO) > 0) {
                // 产生报表数据
                waterElectricityReportService.save4PeakValley(roomId, currentDevice.getDeviceNo(),
                        currentDevice.getDeviceThirdNo(), WaterElectricityReportType.ELECTRICITY.getCode(), currentDevice.getTenantId(),
                        usedSpikeAmount.doubleValue(), tbDeviceDosageDo.getSpikeStartReading(), tbDeviceDosageDo.getSpikeEndReading(), PeakValleyEnum.SPIKE.getCode());
            }
            if (usedPeak.compareTo(BigDecimal.ZERO) > 0) {
                // 产生报表数据
                waterElectricityReportService.save4PeakValley(roomId, currentDevice.getDeviceNo(),
                        currentDevice.getDeviceThirdNo(), WaterElectricityReportType.ELECTRICITY.getCode(), currentDevice.getTenantId(),
                        usedPeakAmount.doubleValue(), tbDeviceDosageDo.getPeakStartReading(), tbDeviceDosageDo.getPeakEndReading(), PeakValleyEnum.PEAK.getCode());
            }
            if (usedPlain.compareTo(BigDecimal.ZERO) > 0) {
                // 产生报表数据
                waterElectricityReportService.save4PeakValley(roomId, currentDevice.getDeviceNo(),
                        currentDevice.getDeviceThirdNo(), WaterElectricityReportType.ELECTRICITY.getCode(), currentDevice.getTenantId(),
                        usedPlainAmount.doubleValue(), tbDeviceDosageDo.getPlainStartReading(), tbDeviceDosageDo.getPlainEndReading(), PeakValleyEnum.PLAIN.getCode());
            }
            if (usedValley.compareTo(BigDecimal.ZERO) > 0) {
                // 产生报表数据
                waterElectricityReportService.save4PeakValley(roomId, currentDevice.getDeviceNo(),
                        currentDevice.getDeviceThirdNo(), WaterElectricityReportType.ELECTRICITY.getCode(), currentDevice.getTenantId(),
                        usedValley.doubleValue(), tbDeviceDosageDo.getValleyStartReading(), tbDeviceDosageDo.getValleyEndReading(), PeakValleyEnum.VALLEY.getCode());
            }
            // TODO 发送消息到钱包更新余额 （目前暂时不需要）
//            if (CollectionUtil.isNotEmpty(infoList.getData()) && totalAmount.compareTo(BigDecimal.ZERO) > 0 && charging) {
//
//                SendMessageVo messageVo = new SendMessageVo();
//                messageVo.setAmount(accountAmount.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
//                messageVo.setShareAmount(shareAmount.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
//                messageVo.setDevice(currentDevice.getDeviceNo());
//                messageVo.setMsgId(mesgId);
//                messageVo.setRoomId(String.valueOf(roomId));
//                messageVo.setTradeTime(new Date());
//                messageVo.setCharging("电费");
//                LOGGER.info("发送钱包数据：" + JSONObject.toJSONString(messageVo));
//                boolean send = streamBridge.send("financeAccountBalance-out-0", MessageBuilder.withPayload(messageVo).setHeader("TAGS", "DEDUCT").build());
//                LOGGER.info("发送钱包返回：" + JSONObject.toJSONString(send));
//            }
        } else {
            LOGGER.error("刷新电表失败,版本version冲突,设备编号:{},设备名称:{}", currentDevice.getDeviceNo(), currentDevice.getDeviceName());
        }
    }

    /**
     * 第三方公共业务-设置电表合闸
     *
     * @param ammeterSwitchOnOffReqVO
     * @return
     */
    @Override
    public ResultModel<AmmeterSwitchOnOffResVO> setAmmeterSwitchOn(AmmeterSwitchOnOffReqVO ammeterSwitchOnOffReqVO) throws Exception {
        TbDeviceDo tbDeviceDo = ammeterDataAccess.getAmmeterInfoByDeviceNo(ammeterSwitchOnOffReqVO.getDeviceNo());
        ammeterSwitchOnOffReqVO.setTbDeviceDo(tbDeviceDo);
        ResultModel<AmmeterSwitchOnOffResVO> resultModel = null;
        ResultModel<AccessTokenResponseWrapperModel> accessTokenResultModel = this.getAccessToken(ammeterSwitchOnOffReqVO.getTbDeviceDo().getApiNo());
        if (ResultModel.CODE_SUCCESS.equals(accessTokenResultModel.getCode())) {
            AccessTokenResponseWrapperModel accessTokenResultModelData = accessTokenResultModel.getData();
            ThirdInstanceService thirdInstanceService = ThirdInstanceFactory.produce(ammeterSwitchOnOffReqVO.getTbDeviceDo().getBrandNo());
            OperateThirdDeviceResponseModel operateThirdDeviceResponseModel = thirdInstanceService.switchAmmeterOn(new OperateThirdDeviceRequestModel()
                    .setAccessToken(accessTokenResultModel.getData().getAccessToken())
                    .setDeviceThirdNo(ammeterSwitchOnOffReqVO.getTbDeviceDo().getDeviceThirdNo())
                    .setLoginName(accessTokenResultModelData.getAppId())
                    .setLoginKey(accessTokenResultModelData.getAppKey()));
            if (operateThirdDeviceResponseModel.getOperateResult()) {
                boolean updateResult = ammeterDataAccess.updateAmmeterSwitchOnoff(tbDeviceDo.getDeviceNo(), 1);
                resultModel = ResultModel.createSuccess();
            } else {
                resultModel = ResultModel.createNativeFail(operateThirdDeviceResponseModel.getOperateMessage());
            }
        } else {
            resultModel = ResultModel.createFail(accessTokenResultModel.getCode(), accessTokenResultModel.getMsg());
        }

        resultModel.setData(new AmmeterSwitchOnOffResVO().setPowerStatus(1).setDeviceNo(ammeterSwitchOnOffReqVO.getDeviceNo()));
        return resultModel;
    }


    /**
     * 第三方公共业务-设置电表跳闸
     *
     * @param ammeterSwitchOnOffReqVO
     * @return
     */
    @Override
    public ResultModel<AmmeterSwitchOnOffResVO> setAmmeterSwitchOff(AmmeterSwitchOnOffReqVO ammeterSwitchOnOffReqVO) throws Exception {

        ResultModel<AmmeterSwitchOnOffResVO> resultModel = null;
        TbDeviceDo tbDeviceDo = ammeterDataAccess.getAmmeterInfoByDeviceNo(ammeterSwitchOnOffReqVO.getDeviceNo());
        ammeterSwitchOnOffReqVO.setTbDeviceDo(tbDeviceDo);
        ResultModel<AccessTokenResponseWrapperModel> accessTokenResultModel = this.getAccessToken(ammeterSwitchOnOffReqVO.getTbDeviceDo().getApiNo());
        if (ResultModel.CODE_SUCCESS.equals(accessTokenResultModel.getCode())) {
            AccessTokenResponseWrapperModel accessTokenResultModelData = accessTokenResultModel.getData();
            ThirdInstanceService thirdInstanceService = ThirdInstanceFactory.produce(ammeterSwitchOnOffReqVO.getTbDeviceDo().getBrandNo());
            OperateThirdDeviceResponseModel operateThirdDeviceResponseModel = thirdInstanceService.switchAmmeterOff(new OperateThirdDeviceRequestModel()
                    .setAccessToken(accessTokenResultModel.getData().getAccessToken())
                    .setDeviceThirdNo(ammeterSwitchOnOffReqVO.getTbDeviceDo().getDeviceThirdNo())
                    .setLoginName(accessTokenResultModelData.getAppId())
                    .setLoginKey(accessTokenResultModelData.getAppKey()));

            if (operateThirdDeviceResponseModel.getOperateResult()) {
                boolean updateResult = ammeterDataAccess.updateAmmeterSwitchOnoff(tbDeviceDo.getDeviceNo(), 0);
                resultModel = ResultModel.createSuccess();
            } else {
                resultModel = ResultModel.createNativeFail(operateThirdDeviceResponseModel.getOperateMessage());
            }
        } else {
            resultModel = ResultModel.createFail(accessTokenResultModel.getCode(), accessTokenResultModel.getMsg());
        }
        resultModel.setData(new AmmeterSwitchOnOffResVO().setPowerStatus(0).setDeviceNo(ammeterSwitchOnOffReqVO.getDeviceNo()));
        return resultModel;
    }


    /**
     * 电表用电明细
     *
     * @param ammeterReportReqVO
     * @return
     */
    @Override
    public ResultModel<AmmeterReportResVO> getAmmeterReport(WaterMeterReportRequestModel ammeterReportReqVO) {


        AmmeterReportResVO ammeterReportResVO = new AmmeterReportResVO();
        List<AmmeterReportListVO> ammeterReportListVOList = new ArrayList<>();
        //根据设备编号查询合同开始时间，将开始时间赋值给查询开始时间，结束时间设置为当天
        if (ObjectUtil.isEmpty(ammeterReportReqVO.getQueryBeginTime())) {
            ResultModel<RoomContractVO> queryResult = iotRoomDeviceApi.queryRoomContract(ammeterReportReqVO.getDeviceNo());
            if (ResultModel.CODE_SUCCESS.equals(queryResult.getCode())) {
                if (null != queryResult.getData()) {
                    LocalDateTime localDateTime = queryResult.getData().getStartTime().atStartOfDay();
                    long beginTimestamp = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                    long endTimestamp = LocalDate.now().plusDays(1).atStartOfDay().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
                    ammeterReportReqVO.setQueryBeginTime(beginTimestamp);
                    ammeterReportReqVO.setQueryEndTime(endTimestamp);
                }
            }
        }
        //查询时间间隔内的该设备的用电明细记录
        List<TbDeviceDosageDo> tbDeviceDosageDoList = deviceDosageDataAccess.getDeviceDosageByDeviceNoAndTimeNoPage(ammeterReportReqVO);
        //总金额
        BigDecimal allTotalAmountMoney = BigDecimal.ZERO;
        for (TbDeviceDosageDo tbDeviceDosageDo : tbDeviceDosageDoList) {
            allTotalAmountMoney = allTotalAmountMoney
                    .add(BigDecimal.valueOf(tbDeviceDosageDo.getAmount()))
                    .add(BigDecimal.valueOf(tbDeviceDosageDo.getSpikeAmount()))
                    .add(BigDecimal.valueOf(tbDeviceDosageDo.getPeakAmount()))
                    .add(BigDecimal.valueOf(tbDeviceDosageDo.getPlainAmount()))
                    .add(BigDecimal.valueOf(tbDeviceDosageDo.getValleyAmount()));
        }
        //处理分页数据
        int size = tbDeviceDosageDoList.size();
        int pageCount = size / ammeterReportReqVO.getPageSize();
        int fromIndex = ammeterReportReqVO.getPageSize() * (ammeterReportReqVO.getPageNum() - 1);
        int toIndex = fromIndex + ammeterReportReqVO.getPageSize();
        if (toIndex >= size) {
            toIndex = size;
        }
        if (ammeterReportReqVO.getPageNum() > pageCount + 1) {
            fromIndex = 0;
            toIndex = 0;
        }
        List<TbDeviceDosageDo> tbDeviceDosageDos = tbDeviceDosageDoList.subList(fromIndex, toIndex);
        for (TbDeviceDosageDo tbDeviceDosageDo : tbDeviceDosageDos) {
            AmmeterReportListVO ammeterReportListVO = new AmmeterReportListVO();
            ammeterReportListVO.setDosageDate(tbDeviceDosageDo.getDosageDate());
            ammeterReportListVO.setStartAmount(tbDeviceDosageDo.getStartAmount());
            ammeterReportListVO.setEndAmount(tbDeviceDosageDo.getEndAmount());
            // 总用量 = 常规用量 + 尖峰平谷用量 (理论上常规是不与尖峰平谷同时存在的，但是不妨碍相加，注意判空就好 deviceDosageDataAccess.getDeviceDosageByDeviceNoAndTimeNoPage 出来的值默认不会为null的了)
            Double spikeReading = tbDeviceDosageDo.getSpikeEndReading() - tbDeviceDosageDo.getSpikeStartReading(); // 尖用量
            Double peakReading = tbDeviceDosageDo.getPeakEndReading() - tbDeviceDosageDo.getPeakStartReading(); // 峰用量
            Double plainReading = tbDeviceDosageDo.getPlainEndReading() - tbDeviceDosageDo.getPlainStartReading(); // 平用量
            Double valleyReading = tbDeviceDosageDo.getValleyEndReading() - tbDeviceDosageDo.getValleyStartReading(); // 谷用量
            Double totalReading = tbDeviceDosageDo.getTotalAmount() + spikeReading + peakReading + plainReading + valleyReading;
            ammeterReportListVO.setSpikeReading(spikeReading);
            ammeterReportListVO.setPeakReading(peakReading);
            ammeterReportListVO.setPlainReading(plainReading);
            ammeterReportListVO.setValleyReading(valleyReading);
            ammeterReportListVO.setTotalAmount(totalReading);

            ammeterReportListVO.setTotalAmountMoney(tbDeviceDosageDo.getAmount() + tbDeviceDosageDo.getSpikeAmount() + tbDeviceDosageDo.getPeakAmount() + tbDeviceDosageDo.getPlainAmount() + tbDeviceDosageDo.getValleyAmount());
            ammeterReportListVOList.add(ammeterReportListVO);
        }
        PageInfo<AmmeterReportListVO> pageInfo = new PageInfo<AmmeterReportListVO>(ammeterReportListVOList);
        pageInfo.setTotal(tbDeviceDosageDoList.size());
        ammeterReportResVO.setPageInfo(pageInfo);
        ammeterReportResVO.setAllTotalAmountMoney(allTotalAmountMoney.setScale(3, BigDecimal.ROUND_HALF_UP).doubleValue());
        return ResultModel.createSuccess(ammeterReportResVO);
    }


    private ResultModel<AccessTokenResponseWrapperModel> getAccessToken(String apiNo) throws Exception {
        TbAccountDo tbAccountDo = tbAccountDataAccess.getThirdApiByApiNo(apiNo);
        AccessTokenRequestWrapperModel accessTokenRequestWrapperModel = new AccessTokenRequestWrapperModel();
        accessTokenRequestWrapperModel.setApiNo(tbAccountDo.getApiNo());
        ResultModel<AccessTokenResponseWrapperModel> accessTokenResultModel = localAccessTokenServcie.getAccessToken(accessTokenRequestWrapperModel);
        return accessTokenResultModel;
    }


    /**
     * 电表详情
     *
     * @param ammeterInfoReqModel
     * @return
     */
    @Override
    public ResultModel<AmmeterInfoResModel> getAmmeterInfo(AmmeterInfoReqModel ammeterInfoReqModel) {
        AmmeterInfoResModel ammeterInfoResModel = new AmmeterInfoResModel();
        //获取设备uuid(IOT设备统一uuid)
        String deviceNo = ammeterInfoReqModel.getDeviceNo();
        TbDeviceDo tbDeviceDo = ammeterDataAccess.getAmmeterInfoByDeviceNo(deviceNo);
        BeanCopier.create(TbDeviceDo.class, AmmeterInfoResModel.class, false).copy(tbDeviceDo, ammeterInfoResModel, null);
        //计算剩余金额（四舍五入）
        LocalDateTime reportTime = tbDeviceDo.getReportTime();
        ZoneId zoneId = ZoneId.systemDefault();
        Instant instant = reportTime.atZone(zoneId).toInstant();
        Date date = Date.from(instant);
        ammeterInfoResModel.setReportTime(date);
        return ResultModel.createSuccess(ammeterInfoResModel);
    }

    @Override
    public void updateSage(DeviceDosageVo deviceDosageVo) {
        SendMessageVo messageVo = new SendMessageVo();
        Double amount = 0.0;
        if (deviceDosageVo.getPayType().equals("laterPay")) {
            //获取本次抄表金额
            BigDecimal totalAmount = BigDecimal.valueOf(deviceDosageVo.getEndAmount()).subtract(BigDecimal.valueOf(deviceDosageVo.getStartAmount()));
            amount = (totalAmount.multiply(BigDecimal.valueOf(deviceDosageVo.getPrice()))).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();

        } else if (deviceDosageVo.getPayType().equals("beforePay")) {
            TbDeviceDo deviceByDeviceNo = deviceDataAccess.getDeviceByDeviceNo(deviceDosageVo.getDeviceNo());
            Calendar now = Calendar.getInstance();
            int year = now.get(Calendar.YEAR);
            Double readAllAccount = 0.0;
            //获取总度数
            DevicePrice devicePrice = devicePriceAccess.getDevicePriceVo(Long.valueOf(year), deviceDosageVo.getDeviceNo());
            if (null != devicePrice) {
                readAllAccount = devicePrice.getReadAccount();
            }
            //本次消费度数
            BigDecimal totalAmount = BigDecimal.valueOf(deviceDosageVo.getEndAmount()).subtract(BigDecimal.valueOf(deviceByDeviceNo.getCurrentReading()));
            //获取本次消费金额
            CommonResult<List<PriceInfo>> infoList = roomDeviceApi.getDevicePrice(deviceDosageVo.getDeviceNo(), deviceDosageVo.getDeviceType());
            BigDecimal readamount = SendMqMessageUtil.compute(BigDecimal.valueOf(readAllAccount).subtract(totalAmount), BigDecimal.valueOf(readAllAccount), infoList.getData());
            amount = readamount.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        messageVo.setAmount(amount);
        messageVo.setDevice(deviceDosageVo.getDeviceNo());
        messageVo.setMsgId(UUID.randomUUID().toString());
        messageVo.setRoomId(String.valueOf(deviceDosageVo.getRoomId()));
        messageVo.setTradeTime(new Date());
        messageVo.setCharging("电费");
        TbDeviceDo currentDevice = new TbDeviceDo();
        streamBridge.send("financeAccountBalance-out-0", MessageBuilder.withPayload(messageVo).setHeader("TAGS", "DEDUCT").build());
    }
}
